﻿using SerialPortTool.Unity;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.IO;
using System.IO.Ports;
using System.Linq;
using System.Text;
using System.Threading;
using System.Timers;
using System.Windows.Forms;
using WinformControls.Forms;

namespace SerialPortTool
{
    public partial class Form1 : FrmWithTitle, ILog
    {
        SerialPortHand serial = new SerialPortHand();
        Int32 ReceiveByte_Cnt = 0;  // 串口操作，接收字节计数
        Int32 SendByte_Cnt = 0;  // 串口操作，发送字节计数
        public List<string> SendData = new List<string>();
        System.Timers.Timer timer = null;
        public bool IsAutoSend { get; set; }
        public Form1()
        {
            InitializeComponent();
            Console.SetOut(new TextBoxWriter(tboxConsole));
            serial.CallDataBackEvent += Serial_CallDataBackEvent;
            serial.Logger = this;
            this.Load += Form1_Load;
        }

        private void Form1_Load(object sender, EventArgs e)
        {
            timer = new System.Timers.Timer();
            timer.Interval = 400;
            timer.Elapsed += Timer_Elapsed;
            timer.AutoReset = false;
            timer.Enabled = false;
            string[] ports = serial.GetNativePortNames();
            if (ports == null)
            {
                MessageBox.Show(this, "找不到串口连接！", "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
            }
            // 默认串口设置显示
            for (int i = 1; i < ports.Length; i++)
            {
                cmbboxCom.Items.Add("COM" + i);
            }
            foreach (var item in serial.BaudRate)  // 波特率
            {
                cmbBaudRate.Items.Add(item);
            }

            foreach (var item in serial.DataBit) // 数据位
            {
                cmbDataBit.Items.Add(item);
            }
            foreach (string s in Enum.GetNames(typeof(Parity)))
            {
                cmbCheckBit.Items.Add(s);    // 初始化校验位
            }

            foreach (string s in Enum.GetNames(typeof(StopBits)))
            {
                cmbStopBit.Items.Add(s);    // 初始化停止位
            }
            if (cmbboxCom.Items.Count > 0)
                // 下拉默认选择项
                cmbboxCom.SelectedIndex = 0;    // 串口号索引值
            cmbBaudRate.SelectedIndex = 0;  // 波特率索引值
            cmbDataBit.SelectedIndex = 3;  // 数据位索引值
            cmbCheckBit.SelectedIndex = 0;  // 校验位索引值
            cmbStopBit.SelectedIndex = 1;  // 停止位索引值

            serial.IsUse16HexSend = chkbHexSnd.Checked;
            serial.IsUse16HexSHow = chkbHexDisplay.Checked;
        }

        // 打开串口
        private void btnOpen_Click(object sender, EventArgs e)
        {
            var btn = sender as Button;  // 将sender(object)转换成button对象
            IsDefaletViserble();
            if (btn.Text == "开")
            {
                // 声明串口中的各个参数
                string sComNum = cmbboxCom.Text;
                string sBaudRate = cmbBaudRate.Text;
                string sDataBit = cmbDataBit.Text;
                string sCheckBit = cmbCheckBit.Text;
                string sStopBit = cmbStopBit.Text;
                try
                {
                    serial.SetPortName(sComNum);// 串口号
                    serial.SetBaudRate((SerialPortBaudRates)Int32.Parse(sBaudRate)); // 波特率
                    serial.SetDataBits((SerialPortDatabits)Int32.Parse(sDataBit));  // 数据位
                    serial.SetParity((Parity)Enum.Parse(typeof(Parity), sCheckBit)); // 校验位
                    serial.SetStopBits((StopBits)Enum.Parse(typeof(StopBits), sStopBit)); // 停止位
                    serial.SetWriteTimeout(500);  // 设置超时写入时间
                    serial.SetReadTimeout(500);   // 设置超时读取时间
                    serial.OpenSerialPort();      // 打开串口操作
                    if (serial.IsOpen)  // 判定串口为关闭状态
                    {
                        btn.Text = "关";
                        IsEableCombox(false);
                        this.BtSuccess.Visible = true;
                    }
                }
                catch (Exception ex)
                {
                    this.BtErro.Visible = true;
                    MessageBox.Show(this, ex.Message, "提示", MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
            }
            else
            {
                // 关闭串口
                serial.CloseSerialPort();
                if (!serial.IsOpen)  // 判定串口为关闭状态
                {
                    btn.Text = "开";
                    IsEableCombox(true);
                    this.BtDefault.Visible = true;
                    Clear();
                }
            }
        }

        private void chkbHexDisplay_CheckedChanged(object sender, EventArgs e)
        {
            CheckBox checkBox = (CheckBox)sender;
            serial.IsUse16HexSHow = checkBox.Checked;
        }

        private void chkbHexSnd_CheckedChanged(object sender, EventArgs e)
        {
            CheckBox checkBox = (CheckBox)sender;
            serial.IsUse16HexSend = true;
        }

        // 串口数据发送
        private void btnSend_Click(object sender, EventArgs e)
        {
            SendByte_Cnt += serial.SendByteCnt;
            lblSndCnt.Text = SendByte_Cnt.ToString("D");  // 发计数转换成字符串类型放入发计数文本域
            serial.SendData(txtbSndArea.Text);
        }

        private void AutoSBt_Click(object sender, EventArgs e)
        {
            if (!IsAutoSend)
            {
                if (string.IsNullOrEmpty(txtbSndArea.Text))
                {
                    MessageBox.Show("请输入要发送的数据!", "提示", MessageBoxButtons.OK, MessageBoxIcon.Warning);
                    AutoSBt.Checked = false;
                    return;
                }
                SendData.Clear();
                List<string> tempL = txtbSndArea.Text.Split(',').ToList();
                foreach (var item in tempL)
                {
                    if (!string.IsNullOrEmpty(item))
                        SendData.Add(item);
                }
                IsAutoSend = true;
                AutoSBt.Checked = true;
            }
            else
            {
                AutoSBt.Checked = false;
                SendData.Clear();
                IsAutoSend = false;
                Clear();
            }
        }

        private void Clear()
        {
            timer.Enabled = false;
        }

        private void Timer_Elapsed(object sender, ElapsedEventArgs e)
        {
            Random rd = new Random();
            int index = rd.Next(SendData.Count);
            serial.SendData(SendData[index]);
        }

        // 数据接收
        private void Serial_CallDataBackEvent(TEventArgs<DataModel> args)
        {
            if (args.Data.OperType == 0) // 回调数据
            {
                Thread.Sleep(100);
                ReceiveByte_Cnt += serial.ReceiveByteCnt;   // 修改收计数
                this.Invoke((EventHandler)(delegate    // 跨线程访问ui资源，使用invoke方式同步ui
                {
                    lblRcvCnt.Text = ReceiveByte_Cnt.ToString("D");
                    txtbRcvArea.AppendText(args.Data.Data1);//追加到接收数据显示框中
                }));
                if (IsAutoSend)
                {
                    timer.Enabled = true;
                }
            }
            else  // 错误数据
            {
                Clear();
                Console.WriteLine("Serial_CallDataBackEvent---->发送的数据有错误!!!");
            }
        }

        // 计数清零
        private void btnClrCnt_Click(object sender, EventArgs e)
        {
            ReceiveByte_Cnt = 0;  // 收计数初始为0
            SendByte_Cnt = 0;     // 发计数初始为0
            lblRcvCnt.Text = ReceiveByte_Cnt.ToString("D");  // 收计数转换成字符串放入接收计数标签
            lblSndCnt.Text = SendByte_Cnt.ToString("D");     // 发计数转换成字符串放入发送计数标签
        }

        // 清除数据发送区域
        private void btnClrSnd_Click(object sender, EventArgs e)
        {
            txtbSndArea.Text = string.Empty;  // 清除数据发送区（Empty为不分配存储空间）
        }

        // 清除数据接收区域
        private void btnClrRcv_Click(object sender, EventArgs e)
        {
            txtbRcvArea.Text = string.Empty;  // 清除数据接收区（Empty为不分配存储空间）
        }


        /// <summary>
        /// 重绘按钮
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void Button_GreenPaint(object sender, PaintEventArgs e)
        {
            Button bt = sender as Button;
            System.Drawing.Drawing2D.GraphicsPath buttonPath = new System.Drawing.Drawing2D.GraphicsPath();
            System.Drawing.Rectangle newRectangle = bt.ClientRectangle;
            newRectangle.Inflate(-10, -10);
            e.Graphics.DrawEllipse(System.Drawing.Pens.Green, newRectangle);
            newRectangle.Inflate(1, 1);
            buttonPath.AddEllipse(newRectangle);
            bt.Region = new System.Drawing.Region(buttonPath);
        }

        private void Button_DefaultPaint(object sender, PaintEventArgs e)
        {
            Button bt = sender as Button;
            System.Drawing.Drawing2D.GraphicsPath buttonPath = new System.Drawing.Drawing2D.GraphicsPath();
            System.Drawing.Rectangle newRectangle = bt.ClientRectangle;
            newRectangle.Inflate(-10, -10);
            e.Graphics.DrawEllipse(System.Drawing.Pens.Black, newRectangle);
            newRectangle.Inflate(1, 1);
            buttonPath.AddEllipse(newRectangle);
            bt.Region = new System.Drawing.Region(buttonPath);
        }


        private void Button_RedPaint(object sender, PaintEventArgs e)
        {
            Button bt = sender as Button;
            System.Drawing.Drawing2D.GraphicsPath buttonPath = new System.Drawing.Drawing2D.GraphicsPath();
            System.Drawing.Rectangle newRectangle = bt.ClientRectangle;
            newRectangle.Inflate(-10, -10);
            e.Graphics.DrawEllipse(System.Drawing.Pens.DarkRed, newRectangle);
            newRectangle.Inflate(1, 1);
            buttonPath.AddEllipse(newRectangle);
            bt.Region = new System.Drawing.Region(buttonPath);
        }

        private void IsEableCombox(bool isEble)
        {
            cmbboxCom.Enabled = isEble;
            cmbBaudRate.Enabled = isEble;
            cmbDataBit.Enabled = isEble;
            cmbCheckBit.Enabled = isEble;
            cmbStopBit.Enabled = isEble;
        }

        public void IsDefaletViserble()
        {
            this.BtDefault.Visible = false;
            this.BtErro.Visible = false;
            this.BtSuccess.Visible = false;
        }

        #region 日志打印
        public void Debug(string content)
        {
            Console.WriteLine(content);
        }

        public void Error(string content)
        {
            Console.WriteLine(content);
        }

        public void Error(Exception ex)
        {
            Console.WriteLine(string.Format("{0}\r\n{1}", ex.Message, ex.StackTrace));
        }

        public void Info(string content)
        {
            Console.WriteLine(content);
        }

        public void Write(string log)
        {
            Console.WriteLine(log);
        }
        #endregion

        /// <summary>
        /// 清除日志
        /// </summary>
        /// <param name="sender"></param>
        /// <param name="e"></param>
        private void BtClearLog_Click(object sender, EventArgs e)
        {
            this.tboxConsole.Clear();
        }
    }
}
